package com.xiaoke.java1;

import org.junit.Test;

/**
 * @author yd
 * @version 1.0
 * @date 2022/3/1 19:51
 */
public class StringTest5 {
    @Test
    public void test1(){
        String s1 = "a" + "b" + "c"; //编译期优化，等同于 "abc"
        String s2 = "abc";//"abc"一定是放在字符串常量池中，将此地址赋给s2

        /**
         * 最终.java 编译成 .class 在执行.class
         * String s1 = "abc";
         * String s2 = "abc";
         */
        System.out.println(s1 == s2);
        System.out.println(s1.equals(s2));

    }

    @Test
    public void test2(){
        String s1 = "javaEE";
        String s2 = "hadoop";

        String s3 = "javaEEhadoop";
        String s4 = "javaEE" + "hadoop";//编译期优化
        String s5 = s1 + "hadoop";
        String s6 = "javaEE" + s2;
        String s7 = s1 + s2;

        //如果拼接的符号前后出现了变量，则相当于在堆空间new String(),具体的内容为拼接的结果：javaEEhadoop
        System.out.println(s3 == s4);//true
        System.out.println(s3 == s5); //false
        System.out.println(s3 == s6); // false
        System.out.println(s3 == s7 ); // false
        System.out.println(s5 == s6); //false
        System.out.println(s5 == s7);//false
        System.out.println(s6 == s7);//false
        //intern():判断字符串常量池中是否存在javaEEhadoop值，若存在，则返回常量池中javaEEhadoop的地址；
        //若字符串常量池中不存在javaEEhadoop，则在常量池中加载一份javaEEhadoop，并返回此对象的地址
        String s8 = s6.intern();
        System.out.println(s3 == s8);
    }


    @Test
    public void test3(){
        String s1 = "a";
        String s2 = "b";
        String s3 = "ab";
        /*
        如下的s1 + s2 的执行细节 （变量s是我临时定义的)
        ①StringBuilder s = new StringBuilder();
        ②s.append("a")
        ③s.append("b)
        ④s.toString()  ---> 约等于new String("ab")

        补充: 在jdk5.0之后使用的是StringBuilder(),在jdk5.0之前使用的是StringBuffer()
         */
        String s4 = s1 + s2;
        System.out.println(s3 == s4);
    }

    /*
    1.字符串拼接操作不一定使用的是StringBuilder()
    如果拼接符号左右两边都是字符串常量或者常量引用，则仍然使用编译期优化，即非StringBuilder方式
    2. 针对于final修饰类、方法、基本数据类型、引用数据类型的量的结构时，能使用上final的时候建议使用上

     */
    @Test
    public void test4(){
        final String s1 = "a";
        final String s2 = "b";
        String s3 = "ab";

        String s4 = s1 + s2;
        System.out.println(s3 == s4);
    }

    /*
    体会执行效率: 通过StringBuilder的 append() 的方式添加字符串的效率要远高于使用String的字符串拼接方式
    好处: ①StringBuilder的append方式:自始至终只创建一个StringBuilder对象
           使用String的字符串拼接方式: 创建多个StringBuilder和String的对象
          ②使用String的字符串拼接方式: 内存中由于创建了较多的StringBuilder和String的对象,内存占用更大；
          如果进行GC花费额外时间

     改进空间: 在实际开发中，如果基本确定前前后后添加的字符串长度不高于某个限定值，highLevel的情况下，建议使用构造器实例化

        StringBuilder src = new StringBuilder(highLevel); // new char[highLevel]



     */
    @Test
    public void test5(){
        long start = System.currentTimeMillis();
//        method1(100000);//7287ms
        method2(100000);//6ms

        long end = System.currentTimeMillis();

        System.out.println("花费的时间为:" + (end - start));

    }

    public void method1(int highLevel){
        String src = "";

        for (int i = 0; i < highLevel; i++) {
            src = src + "a"; //每次循环都会创建一个StringBuilder、String
        }


    }

    public void method2(int highLevel){
        StringBuilder src = new StringBuilder();

        for (int i = 0; i < highLevel; i++) {
           src.append("a");
        }


    }

    @Test
    public void test6(){

        String  s1 = "xiaoke";
        String s2 = new String("xiaoke");

        System.out.println(s1 == s2);

    }

}
